package api

import (
	"bytes"
	"io/ioutil"
	"net/http"

	"gitee.com/war2001/NiuMaEasyGo/global"
	"gitee.com/war2001/NiuMaEasyGo/model"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/middleware"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/router"
	"gitee.com/war2001/NiuMaEasyGo/service"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// AuthController 认证控制器
type AuthController struct {
	userService model.UserService
}

// NewAuthController 创建认证控制器
func NewAuthController(userService model.UserService) *AuthController {
	return &AuthController{
		userService: userService,
	}
}

// RegisterRoutes 注册路由 (旧方式，保留用于兼容)
func (c *AuthController) RegisterRoutes(r *gin.RouterGroup) {
	// 不需要认证的接口
	r.POST("/auth/login", c.Login)
	// r.POST("/auth/register", c.Register) // 暂不提供注册功能

	// 需要认证的接口
	authRequired := r.Group("/auth")
	authRequired.Use(middleware.JWTAuth())
	{
		authRequired.POST("/logout", c.Logout)
		authRequired.POST("/refresh", c.RefreshToken)
		authRequired.GET("/user/info", c.GetUserInfo)
		authRequired.GET("/menu/list", c.GetMenuList)
		authRequired.GET("/codes", c.GetAccessCodes)
	}
}

// LoginMetadata 登录元数据
func (c *AuthController) LoginMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "登录",
		Path:         "/login",
		Component:    "/login/index",
		Icon:         "login",
		Permission:   "",
		ParentPath:   "",
		MenuType:     "menu",
		MenuCategory: "common",
		Method:       "POST",
		APIPath:      "/auth/login",
		RequireAuth:  false,
		Hidden:       true,
		OrderNum:     1,
	}
}

// LogoutMetadata 退出登录元数据
func (c *AuthController) LogoutMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "退出登录",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "",
		ParentPath:   "",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "POST",
		APIPath:      "/auth/logout",
		RequireAuth:  true,
		Hidden:       true,
		OrderNum:     1,
	}
}

// RefreshTokenMetadata 刷新令牌元数据
func (c *AuthController) RefreshTokenMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "刷新令牌",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "",
		ParentPath:   "",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "POST",
		APIPath:      "/auth/refresh",
		RequireAuth:  true,
		Hidden:       true,
		OrderNum:     1,
	}
}

// GetUserInfoMetadata 获取用户信息元数据
func (c *AuthController) GetUserInfoMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "获取用户信息",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "",
		ParentPath:   "",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "GET",
		APIPath:      "/auth/user/info",
		RequireAuth:  true,
		Hidden:       true,
		OrderNum:     1,
	}
}

// GetMenuListMetadata 获取菜单列表元数据
func (c *AuthController) GetMenuListMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "获取菜单列表",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "",
		ParentPath:   "",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "GET",
		APIPath:      "/auth/menu/list",
		RequireAuth:  true,
		Hidden:       true,
		OrderNum:     1,
	}
}

// GetAccessCodesMetadata 获取权限码元数据
func (c *AuthController) GetAccessCodesMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "获取权限码",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "",
		ParentPath:   "",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "GET",
		APIPath:      "/auth/codes",
		RequireAuth:  true,
		Hidden:       true,
		OrderNum:     1,
	}
}

// LoginRequest 登录请求
type LoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// Login 登录
func (c *AuthController) Login(ctx *gin.Context) {
	// 处理OPTIONS请求
	if ctx.Request.Method == "OPTIONS" {
		ctx.AbortWithStatus(204)
		return
	}

	// 添加调试日志
	zap.L().Info("收到登录请求",
		zap.String("method", ctx.Request.Method),
		zap.String("path", ctx.Request.URL.Path),
		zap.String("origin", ctx.Request.Header.Get("Origin")),
	)

	// 手动设置CORS头
	ctx.Writer.Header().Set("Access-Control-Allow-Origin", ctx.Request.Header.Get("Origin"))
	ctx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")

	// 打印请求体
	body, _ := ioutil.ReadAll(ctx.Request.Body)
	ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
	zap.L().Info("登录请求体", zap.String("body", string(body)))

	var req LoginRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		zap.L().Error("解析登录请求失败", zap.Error(err))
		// 确保错误消息能够正确返回
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code":    http.StatusBadRequest,
			"message": "无效的请求参数: " + err.Error(),
		})
		return
	}

	// 验证用户名和密码
	user, err := c.userService.VerifyPassword(req.Username, req.Password)
	if err != nil {
		zap.L().Error("验证密码失败", zap.Error(err))
		// 确保错误消息能够正确返回
		ctx.JSON(http.StatusUnauthorized, gin.H{
			"code":    http.StatusUnauthorized,
			"message": "用户名或密码错误",
		})
		return
	}

	// 生成JWT令牌
	token, err := middleware.GenerateToken(user.ID, user.Username, user.RoleID)
	if err != nil {
		zap.L().Error("生成令牌失败", zap.Error(err))
		// 确保错误消息能够正确返回
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code":    http.StatusInternalServerError,
			"message": "生成令牌失败: " + err.Error(),
		})
		return
	}

	// 返回令牌和用户信息
	zap.L().Info("登录成功", zap.String("username", user.Username))
	middleware.ResponseSuccess(ctx, gin.H{
		"accessToken": token,
		"user": gin.H{
			"id":          user.ID,
			"username":    user.Username,
			"nickname":    user.Nickname,
			"avatar":      user.Avatar,
			"email":       user.Email,
			"phone":       user.Phone,
			"status":      user.Status,
			"lastLoginAt": user.LastLoginAt,
			"lastLoginIP": user.LastLoginIP,
		},
	})
}

// Logout 退出登录
func (c *AuthController) Logout(ctx *gin.Context) {
	// 检查上下文中是否存在JWT令牌信息
	// BlacklistToken函数会从上下文中获取jwt_claims，而不是直接使用令牌字符串
	if _, exists := ctx.Get("jwt_claims"); exists {
		// 将令牌加入黑名单
		if err := middleware.BlacklistToken(ctx); err != nil {
			zap.L().Error("将令牌加入黑名单失败", zap.Error(err))
		}
	}

	middleware.ResponseSuccess(ctx, gin.H{
		"message": "退出成功",
	})
}

// RefreshToken 刷新令牌
func (c *AuthController) RefreshToken(ctx *gin.Context) {
	// 从请求中获取用户信息
	userID, exists := ctx.Get("user_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到用户信息")
		return
	}

	username, exists := ctx.Get("username")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到用户信息")
		return
	}

	roleID, exists := ctx.Get("role_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到用户信息")
		return
	}

	// 生成新的令牌
	token, err := middleware.GenerateToken(userID.(uint), username.(string), roleID.(uint))
	if err != nil {
		middleware.ResponseInternalError(ctx, "生成令牌失败: "+err.Error())
		return
	}

	// 返回新令牌
	middleware.ResponseSuccess(ctx, gin.H{
		"accessToken": token,
	})
}

// GetUserInfo 获取用户信息
func (c *AuthController) GetUserInfo(ctx *gin.Context) {
	// 从上下文中获取用户ID
	userID, exists := ctx.Get("user_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到用户信息")
		return
	}

	// 获取用户信息
	user, err := c.userService.GetByID(userID.(uint))
	if err != nil {
		middleware.ResponseNotFound(ctx, "用户不存在: "+err.Error())
		return
	}

	// 返回用户信息
	middleware.ResponseSuccess(ctx, gin.H{
		"id":          user.ID,
		"username":    user.Username,
		"nickname":    user.Nickname,
		"avatar":      user.Avatar,
		"email":       user.Email,
		"phone":       user.Phone,
		"status":      user.Status,
		"lastLoginAt": user.LastLoginAt,
		"lastLoginIP": user.LastLoginIP,
	})
}

// GetMenuList 获取菜单列表
func (c *AuthController) GetMenuList(ctx *gin.Context) {
	// 从上下文中获取用户ID和角色ID
	userID, exists := ctx.Get("user_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到用户信息")
		return
	}

	roleID, exists := ctx.Get("role_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到角色信息")
		return
	}

	// 记录日志
	zap.L().Info("获取菜单列表",
		zap.Any("userID", userID),
		zap.Any("roleID", roleID))

	// 从权限服务获取菜单
	permissionService := service.NewPermissionService(global.DB, global.ControllerRegistry)
	menus, err := permissionService.GetUserMenus(uint64(userID.(uint)), 0) // 0表示不指定租户ID
	if err != nil {
		zap.L().Error("获取用户菜单失败", zap.Error(err))
		middleware.ResponseInternalError(ctx, "获取菜单失败: "+err.Error())
		return
	}

	// 转换为前端需要的格式
	frontendMenus := convertToFrontendMenus(menus)
	middleware.ResponseSuccess(ctx, frontendMenus)
}

// GetAccessCodes 获取权限码
func (c *AuthController) GetAccessCodes(ctx *gin.Context) {
	// 从上下文中获取用户ID和角色ID
	userID, exists := ctx.Get("user_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到用户信息")
		return
	}

	roleID, exists := ctx.Get("role_id")
	if !exists {
		middleware.ResponseUnauthorized(ctx, "未获取到角色信息")
		return
	}

	// 记录日志
	zap.L().Info("获取权限码",
		zap.Any("userID", userID),
		zap.Any("roleID", roleID))

	// 从权限服务获取权限码
	permissionService := service.NewPermissionService(global.DB, global.ControllerRegistry)
	accessCodes, err := permissionService.GetUserPermissions(uint64(userID.(uint)), 0) // 0表示不指定租户ID
	if err != nil {
		zap.L().Error("获取用户权限码失败", zap.Error(err))
		middleware.ResponseInternalError(ctx, "获取权限码失败: "+err.Error())
		return
	}

	middleware.ResponseSuccess(ctx, accessCodes)
}

// convertToFrontendMenus 将数据库菜单转换为前端需要的格式
func convertToFrontendMenus(menus []*model.SysMenu) []map[string]interface{} {
	// 创建一个映射表，用于快速查找菜单
	menuMap := make(map[uint64]*model.SysMenu)
	for _, menu := range menus {
		menuMap[uint64(menu.ID)] = menu
	}

	// 找出所有根菜单
	var rootMenus []*model.SysMenu
	for _, menu := range menus {
		if menu.ParentID == 0 || menu.ParentID == uint64(0) {
			rootMenus = append(rootMenus, menu)
		}
	}

	// 转换为前端格式
	result := make([]map[string]interface{}, 0, len(rootMenus))
	for _, root := range rootMenus {
		frontendMenu := convertMenuToFrontend(root, menuMap)
		result = append(result, frontendMenu)
	}

	return result
}

// convertMenuToFrontend 将单个菜单转换为前端格式
func convertMenuToFrontend(menu *model.SysMenu, menuMap map[uint64]*model.SysMenu) map[string]interface{} {
	result := map[string]interface{}{
		"name":      menu.Name,
		"path":      menu.Path,
		"component": menu.Component,
		"meta": map[string]interface{}{
			"title": menu.Name,
			"icon":  menu.Icon,
		},
	}

	// 添加其他元数据
	metaMap := result["meta"].(map[string]interface{})
	if menu.OrderNum > 0 {
		metaMap["order"] = menu.OrderNum
	}
	if menu.KeepAlive {
		metaMap["keepAlive"] = true
	}
	if menu.AlwaysShow {
		metaMap["alwaysShow"] = true
	}

	// 处理子菜单
	children := make([]map[string]interface{}, 0)
	for _, child := range menu.Children {
		// 跳过按钮类型
		if child.Type == "button" {
			continue
		}
		childMenu := convertMenuToFrontend(child, menuMap)
		children = append(children, childMenu)
	}

	if len(children) > 0 {
		result["children"] = children
	}

	return result
}
